//
//  ViewController.m
//  Schematic Library Generator
//
//  Created by Arthur Xu on 2020/10/22.
//

#import "ViewController.h"

@implementation ViewController

ComponentDrawType componentBasic[ComponentType_MAX];

- (void)viewDidLoad {
    [super viewDidLoad];
    _typesArray = [[NSMutableArray alloc]init];
    _referenceArray = [[NSMutableArray alloc]init];
    NSMutableArray* descriptArray = [[NSMutableArray alloc]init];
    NSMutableArray* drawArray = [[NSMutableArray alloc]init];
    NSMutableArray* keyArgumentArray = [[NSMutableArray alloc]init];
    NSMutableArray* plistArray = [[NSMutableArray alloc]init];
    NSString *plistPath = [[NSBundle mainBundle] pathForResource:@"KiCadSymbolSetting"
                                                                  ofType:@"plist"];
    _settinngArray = [[NSArray alloc] initWithContentsOfFile:plistPath];
    for (NSInteger settingIdx = 0; settingIdx < _settinngArray.count; settingIdx ++) {
        NSMutableDictionary * dict = [[NSMutableDictionary alloc]initWithDictionary:_settinngArray[settingIdx]];
        NSString* typ = [[NSString alloc]initWithString:[dict valueForKey:@"type"]];
        NSString* ref = [[NSString alloc]initWithString:[dict valueForKey:@"reference"]];
        NSString* descriptPrefix = [[NSString alloc]initWithString:[dict valueForKey:@"descriptionPrefix"]];
        NSString* draw = [[NSString alloc]initWithString:[dict valueForKey:@"draw"]];
        NSString* keyArg = [[NSString alloc]initWithString:[dict valueForKey:@"keyArgument"]];
        NSString* compPlist = [[NSString alloc]initWithString:[dict valueForKey:@"plist"]];
        [_typesArray addObject:typ];
        [_referenceArray addObject:ref];
        [descriptArray addObject:descriptPrefix];
        draw = [draw stringByReplacingOccurrencesOfString:@"\r" withString:@"\r\n"];
        [drawArray addObject:draw];
        [keyArgumentArray addObject:keyArg];
        compPlist = [compPlist stringByReplacingOccurrencesOfString:@"\r" withString:@"\r\n"];
        [plistArray addObject:compPlist];
    }
    [_ComponentTypePopupButton removeAllItems];
    [_ComponentTypePopupButton addItemsWithTitles:_typesArray];
    _selectedComponentType = nil;
    for (NSInteger i = 0 ; i < ComponentType_MAX; i++) {
        componentBasic[i].keyArgument = keyArgumentArray[i];
        componentBasic[i].description = nil;
        componentBasic[i].draw = drawArray[i];
        componentBasic[i].reference = _referenceArray[i];
        componentBasic[i].datasheet = nil;
        componentBasic[i].footprint = nil;
        componentBasic[i].symbolName = nil;
        componentBasic[i].value = nil;
        componentBasic[i].descriptionPrefix = descriptArray[i];
        componentBasic[i].plist = plistArray[i];
        componentBasic[i].keyword = nil;
    }
    _TransitionStatusText.cell.title = @"Status";
    _TransitionStatusText.backgroundColor = NSColor.clearColor;
    _TransitionStatusText.textColor = NSColor.brownColor;
    _TransitionStatusText.hidden = NO;
    super.view.window.title = @"Schematic Library Generator";
    // Do any additional setup after loading the view.
}


- (void)setRepresentedObject:(id)representedObject {
    [super setRepresentedObject:representedObject];

    // Update the view, if already loaded.
}


-(NSOpenPanel *)openPanelWithTitleMessage:(NSString *)ttMessage chooseFiles:(BOOL)bChooseFiles multipleSelection:(BOOL)bSelection chooseDirectories:(BOOL)bChooseDirc createDirectories:(BOOL)bCreateDirc  AllowedFileTypes:(NSArray *)fileTypes
{
    NSOpenPanel *panel = [NSOpenPanel openPanel];
    //[panel setPrompt:prompt];     // 设置默认选中按钮的显示（OK 、打开，Open ...）
    panel.message = ttMessage;    // 设置面板上的提示信息
    panel.canChooseDirectories = bChooseDirc; // 是否可以选择文件夹
    panel.canCreateDirectories = bCreateDirc; // 是否可以创建文件夹
    panel.canChooseFiles =bChooseFiles;      // 是否可以选择文件
    panel.allowsMultipleSelection = bSelection; // 是否可以多选
    panel.allowedFileTypes = fileTypes;        // 所能打开文件的后缀
    //[panel setDirectoryURL:dirURL];                    // 打开的文件路径
    
    return panel;
}

-(void)showAlert:(NSString*) title message:(NSString*) message
{
    NSAlert* alert = [[NSAlert alloc]init];
    [alert setMessageText:title];
    [alert setInformativeText:message];
    [alert addButtonWithTitle:@"ok"];
    [alert setAlertStyle:NSAlertStyleWarning];
    [alert runModal];
}

-(void) writeKiCadSymbolLibFileHead:(NSString*)path
{
    if ([[NSFileManager defaultManager]fileExistsAtPath:path isDirectory:NO]) {     //Check if output lib/dcm file exist
        NSError* err;
        _libFileAppendData = [[NSString alloc]initWithContentsOfFile:path encoding:NSUTF8StringEncoding error:&err];
        NSMutableArray* libTempArray = [[NSMutableArray alloc]initWithArray:[_libFileAppendData componentsSeparatedByString:@"\r\n"]];
        //if file exist, remove file end part
        [libTempArray removeLastObject];
        [libTempArray removeLastObject];
        _libFileAppendData = [libTempArray componentsJoinedByString:@"\r\n"];
        _fileFixedContent = [[NSMutableArray alloc]init];
        [_fileFixedContent insertObject:_libFileAppendData atIndex:0];
        NSLog(@"lib file head second\r\n");
    } else {
        //if file do not exist, add file start part
        NSString* fileHeadData = @"EESchema-LIBRARY Version 2.4\r\n#encoding utf-8\r\n";
        NSLog(@"lib file head fisrt\r\n");
        _libFileAppendData = [[NSString alloc]initWithString:fileHeadData];
        _fileFixedContent = [[NSMutableArray alloc]init];
    }
}

-(void) writeKiCadSymbolDCMFileHead:(NSString *) path
{
    if ([[NSFileManager defaultManager]fileExistsAtPath:path isDirectory:NO]) {     //Check if output lib/dcm file exist
        NSError * err;
        _DCMFileAppendData = [[NSString alloc]initWithContentsOfFile:path encoding:NSUTF8StringEncoding error:&err];
        NSMutableArray* dcmTempArray = [[NSMutableArray alloc]initWithArray:[_DCMFileAppendData componentsSeparatedByString:@"\r\n"]];
        //if file exist, remove file end part
        [dcmTempArray removeLastObject];
        [dcmTempArray removeLastObject];
        _DCMFileAppendData = [dcmTempArray componentsJoinedByString:@"\r\n"];
        _fileFixedContent = [[NSMutableArray alloc]init];
        [_fileFixedContent insertObject:_DCMFileAppendData atIndex:1];
        NSLog(@"dcm file head second\r\n");
    } else {
        //if file do not exist, add file start part
        NSString* fileHeadData = @"EESchema-DOCLIB  Version 2.0\r\n";
        _DCMFileAppendData = [[NSString alloc]initWithString:fileHeadData];
        NSLog(@"dcm file head fisrt\r\n");
    }
}

-(BOOL)isKeyArgument:(NSArray*) array member:(NSString*) member
{
    if (array.count == 0) {
        return NO;
    }
    else
    {
        for (NSInteger i = 0; i<array.count; i++) {
            if([array[i] isEqual:member])
                return YES;
        }
    }
    return  NO;
}

-(NSMutableArray*) writeKiCadSymbolFile:(ComponentType) type items:(NSMutableArray*) items values:(NSMutableArray *) values
{
    NSError* error;
    _component = componentBasic[type];
    //NSLog(@"%@",componentBasic);
    NSString* componentDCMFileStart = @"#\r\n";
    NSString* componentDCMFileEnd = @"$ENDCMP\r\n";
    NSString* componentLibFileAStart = @"#\r\n# ";
    NSString* componentLibFileAEnd = @"#\r\n#End Library\r\n";
    NSString* componentLibfilePlist = [[NSString alloc]initWithString:_component.plist];
    
    NSInteger idxDes = [items indexOfObject:@"Description"];
    _component.description = values[idxDes];
    NSInteger idxFootprint = [items indexOfObject:@"Footprint"];
    _component.footprint = values[idxFootprint];
    
    _component.keyword = _component.description;
    NSString* ds = [[NSString alloc]init];
    if ([items containsObject:@"Datasheets"]) {
        ds = @"Datasheets";
    }
    else if([items containsObject:@"Datasheet"])
    {
        ds = @"Datasheet";
    }
    else
    {
        [self showAlert:@"CSV file format error" message:@"items does not contain \"Datasheets\" or\"Datasheet\""];
    }
    NSInteger idxDatasheet = [items indexOfObject:ds];
    _component.datasheet = values[idxDatasheet];
    if (![items containsObject:@"PartNumber"]) {
        [self showAlert:@"CSV file format error" message:@"items does not contain \"PartNumber\",or spelling mistake, please double check"];
        return nil;
    }
    NSInteger idxPN = [items indexOfObject:@"PartNumber"];
    _component.symbolName = values[idxPN];;
    _component.value =values[idxPN];
    if (![items containsObject:@"ComponentValue"]) {
        [self showAlert:@"CSV file format error" message:@"items does not contain \"ComponentValue\",or spelling mistake, please double check"];
        return nil;
    }
    //////////////////////////////
    /// Lib file
    //////////////////////////////
    //Lib file start
    NSString* componentContent = [[NSString alloc]init];
    componentContent = [componentLibFileAStart stringByAppendingString:_component.value];
    componentContent = [componentContent stringByAppendingString:@"\r\n#\r\n"];
    //componennt property
        //basic property
    NSInteger y_pos = 0;
    NSString * def = [@"DEF " stringByAppendingString:_component.value];
    def = [def stringByAppendingString:@" C 0 10 N Y 1 F N\r\n"];
    componentContent = [componentContent stringByAppendingString:def];
    NSString* basicProperty = @"F0 \"";
    basicProperty = [basicProperty stringByAppendingString:_component.reference];
    basicProperty = [basicProperty stringByAppendingString:@"\" 25 100 50 H V L CNN\r\n"];
    y_pos = 50;
    componentContent = [componentContent stringByAppendingString:basicProperty];
    basicProperty = @"F1 \"";
    basicProperty = [basicProperty stringByAppendingString:_component.value];
    basicProperty = [basicProperty stringByAppendingString:@"\" 20 -130 10 H V L CNN\r\n"];
    y_pos += 10;
    componentContent = [componentContent stringByAppendingString:basicProperty];
    basicProperty = @"F2 \"";
    basicProperty = [basicProperty stringByAppendingString:_component.footprint];
    basicProperty = [basicProperty stringByAppendingString:@"\" 150 -150 10 H V C CNN\r\n"];
    y_pos += 10;
    componentContent = [componentContent stringByAppendingString:basicProperty];
    basicProperty = @"F3 \"";
    //basicProperty = [basicProperty stringByAppendingString:component.datasheet];
    basicProperty = [basicProperty stringByAppendingString:@"\" -1 0 10 H I C CNN\r\n"];
    y_pos += 10;
    componentContent = [componentContent stringByAppendingString:basicProperty];
        //custom property
    NSArray* argumentArray = [[NSArray alloc]initWithArray: [_component.keyArgument componentsSeparatedByString:@"," ]];
    for (NSInteger i = 0; i<items.count; i++) {
        ItemPeopertyType itemProperty;
        
        NSString* property = [@"F" stringByAppendingString:[NSString stringWithFormat:@"%ld",i+4]];
        itemProperty.itemID = property;
        itemProperty.italic = ITEM_ITALIC_DISABLE;
        itemProperty.bold = ITEM_BOLD_DISABLE;
        itemProperty.horizonType = ITEM_HORIZON_CENTER;
        NSString* itemVal = [[NSString alloc]initWithString:items[i]];
        if([self isKeyArgument:argumentArray member:itemVal])
        {
            itemProperty.visiable = ITEM_VISIABLE;
        }
        else
        {
            itemProperty.visiable = ITEM_INVISIABLE;
        }
        itemProperty.itemValue = values[i];
        if([items[i] isEqual:@"ComponentValue"])
        {
            itemProperty.textSize = @"50";
        }
        else
        {
            itemProperty.textSize = @"10";
        }
        itemProperty.verticalType = ITEM_VERTICAL_CENTER;
        itemProperty.xPos = @"50";
        itemProperty.itemName = items[i];
        y_pos += 20;
        itemProperty.yPos = [NSString stringWithFormat:@"-%ld",y_pos];
        //if(([items[i]  isEqual: @"PartNumber"])||([items[i]  isEqual: @"Tolerance"])||([items[i]  isEqual: @"Voltage"]))
            //continue;
        NSString* itemProper = [NSString stringWithFormat:@"%@ \"%@\" %@ %@ %@ H %@ %@ %@%@%@ \"%@\"\r\n",itemProperty.itemID,itemProperty.itemValue,itemProperty.xPos,itemProperty.yPos,itemProperty.textSize,itemProperty.visiable,itemProperty.horizonType,itemProperty.verticalType,itemProperty.italic,itemProperty.bold,itemProperty.itemName];
        componentContent = [componentContent stringByAppendingString:itemProper];
    }
    //component plist
    componentContent = [componentContent stringByAppendingString:componentLibfilePlist];
    //component draw
    componentContent = [componentContent stringByAppendingString:_component.draw];
    //Lib file end
    componentContent = [componentContent stringByAppendingString:@"ENDDEF\r\n"];
    _libFileAppendData = [_libFileAppendData stringByAppendingString:componentContent];
    _fileFixedContent[0] = _libFileAppendData;
    //////////////////////////////
    /// DCM file
    //////////////////////////////
    //DCM file start
    componentContent = [componentDCMFileStart stringByAppendingFormat:@"%@%@\r\n", @"$CMP ", _component.value ];
    
    componentContent = [componentContent stringByAppendingFormat:@"%@%@%@\r\n",@"D ",_component.descriptionPrefix,_component.description];
    if ([items containsObject:@"Tolerance"]) {
        NSInteger idxPrecision = [items indexOfObject:@"Tolerance"];
        componentContent = [componentContent stringByAppendingFormat:@"%@%@ %@\r\n",@"K",_component.keyword,values[idxPrecision]];
    }
    NSInteger idxdatasheet = [items indexOfObject:ds];
    componentContent = [componentContent stringByAppendingFormat:@"%@ %@\r\n",@"F",values[idxdatasheet]];
    componentContent = [componentContent stringByAppendingString:componentDCMFileEnd];
    _DCMFileAppendData = [_DCMFileAppendData stringByAppendingString:componentContent];
    _fileFixedContent[1] = _DCMFileAppendData;
    return _fileFixedContent;
}

-(void) writeKiCadSymbolLibFileTail
{
    NSString* fileTailData = @"#\r\n#End Library\r\n";
    _libFileAppendData = [_libFileAppendData stringByAppendingString:fileTailData];
    _fileFixedContent[0] = _libFileAppendData;
}

-(void) writeKiCadSymbolDCMFileTail
{
    NSString* fileTailData = @"#\r\n#End Doc Library\r\n";
    _DCMFileAppendData = [_DCMFileAppendData stringByAppendingString:fileTailData];
    _fileFixedContent[1] = _DCMFileAppendData;
}

-(void) removeKiCadSymbolDCMFileTail:(NSString*) data
{
    NSMutableArray* dcmOldDataArray = [[NSMutableArray alloc]initWithArray:[data componentsSeparatedByString:@"\r\n"]];
    [dcmOldDataArray removeLastObject];
    [dcmOldDataArray removeLastObject];
    _DCMFileAppendData = [dcmOldDataArray componentsJoinedByString:@"\r\n"];
}

-(void) removeKiCadSymbolLibFileTail:(NSString*) data
{
    NSMutableArray* libOldDataArray = [[NSMutableArray alloc]initWithArray:[data componentsSeparatedByString:@"\r\n"]];
    [libOldDataArray removeLastObject];
    [libOldDataArray removeLastObject];
    _libFileAppendData = [libOldDataArray componentsJoinedByString:@"\r\n"];
}
     

- (IBAction)componentTypePopUpAction:(id)sender {
    _selectedComponentType = _ComponentTypePopupButton.selectedItem.title;
}


- (IBAction)sourcePathAction:(id)sender {
    NSOpenPanel* soourcepanel = [self openPanelWithTitleMessage:@"please select the csv file" chooseFiles:YES multipleSelection:NO chooseDirectories:NO createDirectories:NO AllowedFileTypes:[NSArray arrayWithObject:@"csv"] ];
    [soourcepanel runModal];
    _sourcePath = soourcepanel.URL.path;
    _sourceFilePathText.cell.title = _sourcePath;
    
}
- (IBAction)outputPathAction:(id)sender {
    NSOpenPanel* outputpanel = [self openPanelWithTitleMessage:@"please select output path" chooseFiles:NO multipleSelection:NO chooseDirectories:YES createDirectories:YES AllowedFileTypes:nil];
    [outputpanel runModal];
    _outputPath = outputpanel.URL.path;
    _outputPathText.cell.title = _outputPath;
}


- (IBAction)startTransition:(id)sender {
    NSError *error;
    NSString *inFileContent;
    NSMutableArray * lineArray;
    
    NSMutableArray * itemsArray;
    NSMutableArray * valueArray;
    _libFileAppendData = [[NSString alloc]init];
    _DCMFileAppendData = [[NSString alloc]init];
    _curLine = 0;
    _TransitionStatusText.cell.title = @"Processing...";
    _TransitionStatusText.backgroundColor = NSColor.blueColor;
    _TransitionStatusText.textColor = NSColor.grayColor;
    sleep(1);
    if ([_sourcePath  isEqual: @""]|| _sourcePath == nil) {
        [self showAlert:@"Source path alert" message:@"please offer a correct csv file path"];
    }
    else if ([_outputPath  isEqual: @""]|| _outputPath == nil) {
        [self showAlert:@"Output path alert" message:@"please offer a correct output directory path"];
    }
    else
    {
        
        //get csv file name
        NSString* fileName = [[_sourcePath componentsSeparatedByString:@"/"]lastObject];
        NSMutableArray* tempFileNameArray =[[NSMutableArray alloc]initWithArray:[fileName componentsSeparatedByString:@"."]];
        [tempFileNameArray removeLastObject];
        //get csv file name
        fileName = [tempFileNameArray componentsJoinedByString:@"."];
        NSString* dcmFilePath = [NSString stringWithFormat:@"%@/%@",_outputPath,[fileName stringByAppendingString:@".dcm"]];;
        NSString* libFilePath = [NSString stringWithFormat:@"%@/%@",_outputPath,[fileName stringByAppendingString:@".lib"]];
        //read csv data
        NSString* csvFileContent = [[NSString alloc]initWithContentsOfFile:_sourcePath encoding:NSUTF8StringEncoding error:&error];
        if (csvFileContent == @"" || csvFileContent == nil) {
            _TransitionStatusText.cell.title = @"Failed";
            _TransitionStatusText.backgroundColor = NSColor.redColor;
            _TransitionStatusText.textColor = NSColor.blackColor;
            [self showAlert:@"Error" message:@"read csv file failed, please double check your csv file, make sure it correct."];
        }
        //check if lib / dcm file exist
        if(0!=access([dcmFilePath cStringUsingEncoding:NSUTF8StringEncoding], 0))
        {
            NSLog(@"dcm file do not exist");
            [self writeKiCadSymbolDCMFileHead:dcmFilePath];
        }
        else
        {
            NSLog(@"dcm file did exist");
            _DCMFileAppendData = [[NSString alloc] initWithContentsOfFile:dcmFilePath encoding:NSUTF8StringEncoding error:&error];
            [self removeKiCadSymbolDCMFileTail:_DCMFileAppendData];
        }
        if(0!=access([libFilePath cStringUsingEncoding:NSUTF8StringEncoding], 0))
        {
            NSLog(@"lib file do not exist");
            [self writeKiCadSymbolLibFileHead:libFilePath];
        }
        else
        {
            NSLog(@"lib file did exist");
            _libFileAppendData = [[NSString alloc] initWithContentsOfFile:libFilePath encoding:NSUTF8StringEncoding error:&error];
            [self removeKiCadSymbolLibFileTail:_libFileAppendData];
        }
        
        lineArray = [[NSMutableArray alloc]initWithArray:[csvFileContent componentsSeparatedByString:@"\r"]];
        itemsArray = [[NSMutableArray alloc] initWithArray:[lineArray[0] componentsSeparatedByString:@","]];
        if(itemsArray.count > 1)
        {
            
            for (NSInteger index_i = 1; index_i < lineArray.count; index_i++) {
                valueArray = [[NSMutableArray alloc] initWithArray:[lineArray[index_i] componentsSeparatedByString:@","]];
                NSInteger type = [_typesArray indexOfObject:_ComponentTypePopupButton.selectedItem.title];
                _curLine = index_i + 1;
                [self writeKiCadSymbolFile:(ComponentType)type items:itemsArray values:valueArray];
                NSLog(@"%ld",(long)index_i);
            }
            [self writeKiCadSymbolDCMFileTail];
            [self writeKiCadSymbolLibFileTail];
            [_libFileAppendData writeToFile:libFilePath atomically:NO encoding:NSUTF8StringEncoding error:&error];
            if(error != nil)
            {
                _TransitionStatusText.cell.title = @"Failed";
                _TransitionStatusText.backgroundColor = NSColor.redColor;
                _TransitionStatusText.textColor = NSColor.blackColor;
                [self showAlert:@"error" message:[NSString stringWithFormat:@"%@",error]];
            }
            [_DCMFileAppendData writeToFile:dcmFilePath atomically:YES encoding:NSUTF8StringEncoding error:&error];
            if(error != nil)
            {
                _TransitionStatusText.cell.title = @"Failed";
                _TransitionStatusText.backgroundColor = NSColor.redColor;
                _TransitionStatusText.textColor = NSColor.blackColor;
                [self showAlert:@"error" message:[NSString stringWithFormat:@"%@",error]];
            }
            _TransitionStatusText.cell.title = @"Success";
            _TransitionStatusText.backgroundColor = NSColor.greenColor;
            _TransitionStatusText.textColor = NSColor.blueColor;
            _libFileAppendData = @"";
            _DCMFileAppendData = @"";
        }
        else
        {
            NSMutableArray* tempItemArray = [[NSMutableArray alloc]initWithArray:[lineArray[0]componentsSeparatedByString:@"\t"]];
            if (tempItemArray.count > 1) {
                _TransitionStatusText.cell.title = @"Failed";
                _TransitionStatusText.backgroundColor = NSColor.redColor;
                _TransitionStatusText.textColor = NSColor.blackColor;
                [self showAlert:@"Error" message:@"csv file format error: delimiter \"\\t\" exist at each line, which should be delimiter \",\"."];
            }
            else
            {
                _TransitionStatusText.cell.title = @"Failed";
                _TransitionStatusText.backgroundColor = NSColor.redColor;
                _TransitionStatusText.textColor = NSColor.blackColor;
                [self showAlert:@"Error" message:@"csv file format error: delimiter \",\" does not exist, please reeidt csv file and save as csv format."];
            }
            
        }
        
    }
}



@end
